package net.xdlass.component;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;


/**
 * 配置类，用于创建和配置RestTemplate实例
 */
@Configuration
public class RestTemplateConfig {
    /**
     * 创建并返回一个RestTemplate实例，用于执行HTTP请求。
     * RestTemplate是Spring提供的用于访问REST服务的客户端工具。
     *
     * @param requestFactory ClientHttpRequestFactory实例，用于创建HTTP请求。
     *                       通过传入的自定义请求工厂，可以控制HTTP请求的创建过程。
     * @return RestTemplate实例，配置了自定义的请求工厂，用于执行HTTP请求。
     */
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
        return new RestTemplate(requestFactory);
    }

    /**
     * 创建并返回一个ClientHttpRequestFactory实例，用于创建HTTP请求。
     * 该工厂基于Apache的HttpComponentsClientHttpRequestFactory实现，支持连接池和高级配置。
     *
     * @return ClientHttpRequestFactory实例，配置了自定义的HttpClient，用于创建HTTP请求。
     */
    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    /**
     * 创建并配置一个HttpClient实例，用于执行HTTP请求。
     * 该HttpClient配置了连接池、超时设置等，以提高性能和可靠性。
     *
     * @return CloseableHttpClient实例，配置了连接池和请求超时设置，用于执行HTTP请求。
     */
    @Bean
    public HttpClient httpClient() {
        // 创建一个注册表，用于管理和创建HTTP和HTTPS连接的Socket工厂。
        // 注册表包含HTTP和HTTPS的Socket工厂，分别用于处理普通HTTP请求和加密HTTPS请求。
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        // 创建一个池化连接管理器，用于管理HTTP连接池。
        // 连接池可以复用HTTP连接，减少创建和销毁连接的开销，提高性能。
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

        // 设置连接池的最大连接数为500。
        // 这是整个连接池的最大连接数，适用于所有路由。
        connectionManager.setMaxTotal(500);

        // 设置每个路由的默认最大连接数为300。
        // 路由是指目标主机（域名），此设置限制了每个主机的最大并发连接数。
        connectionManager.setDefaultMaxPerRoute(300);

        // 创建请求配置，设置Socket超时、连接超时和获取连接的超时时间。
        // 这些超时设置用于控制HTTP请求的执行时间，防止请求长时间阻塞。
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置Socket超时时间为20秒，即从服务器读取数据的超时时间。
                .setSocketTimeout(20000)
                // 设置连接超时时间为10秒，即与服务器建立连接的超时时间。
                .setConnectTimeout(10000)
                // 设置从连接池中获取连接的超时时间为1秒。
                .setConnectionRequestTimeout(1000)
                .build();

        // 创建并配置HttpClient实例。
        // 使用HttpClientBuilder构建HttpClient，设置默认的请求配置和连接管理器。
        CloseableHttpClient closeableHttpClient = HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();

        // 返回配置好的HttpClient实例。
        return closeableHttpClient;
    }

}
